using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;

using HtmlParsing.Exceptions;
using Helpers.FastToString;


namespace HtmlParsing.Tegs
{
  public abstract class TegBase
  {
    private const string NULL_VALUE_STR = "<<<NULL>>>";

    public TegBase(string tegString)
    {
      TegString = tegString;
      Parse();
    }

    public abstract string TegName
    {
      get;
    }

    protected abstract void Parse();


    protected string PrepareTegString(string tegString)
    {
      string teg = tegString;
      teg = teg.Replace("\"", "'");
      while (teg.Contains(" ="))
        teg = teg.Replace(" =", "=");
      while (teg.Contains(" ="))
        teg = teg.Replace(" =", "=");
      while (teg.Contains("< "))
        teg = teg.Replace("< ", "<");
      teg = teg.Replace("<", "< ");
      while (teg.Contains(" >"))
        teg = teg.Replace(" >", ">");
      teg = teg.Replace(">", " >");

      return teg;
    }

    protected string GetAttributeValue(string attributeName, string tegString)
    {
      string attrNameUp = attributeName.ToUpper().Trim();
      string teg = PrepareTegString(tegString);
      string tegUp = teg.ToUpper();

      Regex re = new Regex(attrNameUp + @"=[^\s]+");
      MatchCollection ms = re.Matches(tegUp);
      if (ms == null || ms.Count < 1)
        return null;
      if (ms.Count > 1)
        throw new InvalidTegFormatException("Teg " + TegName.ToUpper() + " contains more than 1 " + attrNameUp + " attribute!");
      string attrStr = teg.Substring(ms[0].Index, ms[0].Length);
      string[] attrParts = attrStr.Split('=');
      if (attrParts.Length > 1)
      {
        string result = attrParts[1];
        for (int i = 2; i < attrParts.Length; i++)
          result += "=" + attrParts[i];
        return result.Replace("'", String.Empty);
      }
      else
        return String.Empty;
    }

    public override string ToString()
    {
      string res = String.Empty;
      foreach (PropertyInfo pi in this.GetType().GetProperties())
      {
        object[] attrs = pi.GetCustomAttributes(typeof(PrintableAttrAttribute), true);
        if (attrs.Length < 1)
          continue;

        string publicName = (attrs[0] as PrintableAttrAttribute).PublicName;
        if (publicName == null)
          publicName = pi.Name;

        object oPropertyValue = pi.GetValue(this, null);
        string sPropertyValue = oPropertyValue == null ? NULL_VALUE_STR : oPropertyValue.ToString();

        res += publicName + " = |" + sPropertyValue + "|" + Environment.NewLine;
      }
      return res;
    }

    private string _tegString = null;
    public string TegString
    {
      get { return _tegString; }
      set { _tegString = value; }
    }

    public string TegContent
    {
      get { return OpenTeg + TegInnerText + CloseTeg; }
    }

    private string _tegInnerText = null;
    public string TegInnerText
    {
      get { return _tegInnerText; }
      set { _tegInnerText = value; }
    }

    private string _openTeg = null;
    public string OpenTeg
    {
      get { return _openTeg; }
      set { _openTeg = value; }
    }

    private string _closeTeg = null;
    [PrintableAttr()]
    public string CloseTeg
    {
      get { return _closeTeg; }
      set { _closeTeg = value; }
    }
  }
}
